﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
namespace dungeon_brawler.classes
{
    public abstract class Entity
    {
        public Vector2 position;
        protected Texture2D texture;
        protected int lvl, hp, atk, def;
        protected bool isAtk = false;
        protected double cooldown;
        protected int spd;// walking spd
        protected Vector2 direction;// The direction the actor is facing -> +X east -X west -Y north +Y south
        protected Point frameSize = new Point(32,32);// Keep this fixed for the time being
        /// <summary>
        /// Accessors/modifiers
        /// </summary>
        public int collisionOffset { get; protected set; }
        public int atkOffset { get; protected set ; }// Size of attack area
        public Rectangle collisionRect
        {
            get
            {
                return new Rectangle(
                (int)(position.X + (collisionOffset)),
                (int)(position.Y + (collisionOffset)),
                (int)((frameSize.X - (collisionOffset * 2))),
                (int)((frameSize.Y - (collisionOffset * 2))));
            }
        }
        public Rectangle atkRect
        {
            get
            {
                if (direction.X > 0)// east
                {
                    return new Rectangle(
                       (int)((position.X)),
                       (int)((position.Y)),
                       (int)((position.X + frameSize.X) + atkOffset),
                       (int)(position.Y + frameSize.Y));
                }
                else if (direction.X < 0)// west
                {
                    return new Rectangle(
                       (int)(position.X + frameSize.X),
                       (int)(position.Y),
                       (int)(position.X) - atkOffset,
                       (int)((position.Y + frameSize.Y)));
                }
                else if (direction.Y > 0)// south
                {
                    return new Rectangle(
                        (int)((position.X)),
                        (int)((position.Y)),
                        (int)(position.X + frameSize.X),
                        (int)((position.Y + frameSize.Y) + atkOffset));
                }
                else if (direction.Y < 0)// north
                {
                    return new Rectangle(
                        (int)((position.X)),
                        (int)((position.Y - atkOffset)),
                        (int)(position.X + frameSize.X),
                        (int)(position.Y + frameSize.Y));
                }
                return Rectangle.Empty;
            }
        }
        public int     Atk      { get { return atk;      } protected set { atk      = value;} }
        public int     Hp       { get { return hp;       } protected set { hp       = value;} }
        public int     Def      { get { return def;      } protected set { def      = value;} }
        public int     Lvl      { get { return lvl;      } protected set { lvl      = value;} }
        public Vector2 Position { get { return position; } protected set { position = value;} }
        public int     Spd      { get { return spd;      }  set { spd      = value;} }
        public bool    IsAtk    { get { return isAtk;    } protected set { isAtk    = value;} }

        public Entity(Vector2 position, Texture2D texture) : this(1, position, texture)
        {}

        // We need to alter the attributes so that it is increased accordding to given level!
        public Entity(int lvl, Vector2 position, Texture2D texture)
        {
            this.position = position;
            this.texture = texture;
            this.lvl = lvl;
            // Set base attribs
            hp  = 40;
            def = 40;
            hp  = 40;
            //isAtk = false;
        }

        /// <summary>
        /// attack function
        /// </summary>
        public void attack()
        {

        }

        /// <summary>
        /// function for when entity is attacked
        /// </summary>
        /// <param name="attacker"></param>
        public void hit(Entity attacker)
        {
            
        }

        /// <summary>
        /// Levels up a character
        /// </summary>
        public void lvlUp()
        {
            lvlUp(1); // Just incr level by one
        }


        /// <summary>
        /// Levels up a character to a specified level
        /// </summary>
        public void lvlUp(int increment)
        {
            // Level up for as long as increment says
            for (int i = 0; i < increment; i++)
            {
                // Incr stats by 20%
                hp += (hp / 5);
                def += (def / 5);
                atk += (atk / 5);
            }
                
        }

         //needs to be public and virtual because we will be changing it later
        public virtual void Update(GameTime gameTime, Rectangle clientBounds)
        {}

        //public draw method to allow each actor to draw itself
        public void Draw(SpriteBatch spriteBatch)
        {

            spriteBatch.Draw(texture, new Vector2(position.X + 32, position.Y + 32),
                new Rectangle(0,
                    0,
                    frameSize.X,
                    frameSize.Y), Color.White, 0, new Vector2(texture.Width/2, texture.Height/2), 1, SpriteEffects.None, 1);
        }

        /// <summary>
        /// Returns class stats
        /// </summary>
        /// <returns>String</returns>
        public override String ToString()
        {
            return 
                "\nHP     " + Hp + 
                "\nATCK   " + Atk + "        DEF   " + Def +
                "\nPos    " + Math.Ceiling(Position.X) + " , " + Math.Ceiling(Position.Y) +
                "\nDir    " + Math.Ceiling(direction.X) + " , " + Math.Ceiling(direction.Y) +
                "\nCldwn  " + cooldown;
        }
    }
}
